package com.dfl.guistore.service

import android.app.Service
import android.content.Intent
import android.os.RemoteCallbackList
import android.util.Log
import com.dfl.api.app.guistore.ISkinService
import com.dfl.api.app.guistore.ISkinServiceCallback
import com.dfl.api.app.guistore.SkinInfo
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

class SkinService : Service() {
    private val skinInfoA = SkinInfo(1L, "", true, false, "", "")
    private val skinInfoB = SkinInfo(2L, "", true, false, "", "")
    private val remoteCallbackList = RemoteCallbackList<ISkinServiceCallback>()

    private val binder by lazy {
        object : ISkinService.Stub() {
            override fun registerSkinCallback(callback: ISkinServiceCallback?) {
                callback ?: return
                remoteCallbackList.register(callback)
                runBlocking { prepareForChangeSkin(skinInfoB) }

                runBlocking { prepareForChangeSkin(skinInfoA) }
            }

            override fun unregisterSkinCallback(callback: ISkinServiceCallback?) {
                callback ?: return
                remoteCallbackList.unregister(callback)
            }

            override fun getUsingSkin(): SkinInfo {
                return skinInfoA
            }
        }
    }

    override fun onBind(intent: Intent?) = binder

    private suspend fun prepareForChangeSkin(skinInfo: SkinInfo) {
        (0..5).reversed().forEach {
            Log.i("ChangeSkin[service]", "changeSkin countdown: $it")
            delay(1000)
        }

        val start = System.currentTimeMillis()

        val count = remoteCallbackList.beginBroadcast()
        try {
            val handleSuccess = sequence {
                for (index in 0 until count) {
                    val client = remoteCallbackList.getBroadcastItem(index)
                    val result = client.onHandleSkin(skinInfo)
                    yield(result)
                }
            }.all { it }
            if (!handleSuccess) {
                Log.e("ChangeSkin[service]", "handle skin[${skinInfo.skinId}] failure")
                return
            }

            val changeSuccess = sequence {
                for (index in 0 until count) {
                    val client = remoteCallbackList.getBroadcastItem(index)
                    val result = client.onSkinPathChanged(skinInfo)
                    yield(result)
                }
            }.all { it }

            if (!changeSuccess) {
                Log.e("ChangeSkin[service]", "change skin[${skinInfo.skinId}] failure")
                return
            }

            Log.i("ChangeSkin[service]", "change skin all success")
        } catch (e: Throwable) {
            Log.e("ChangeSkin[service]", "change skin exception", e)
        } finally {
            remoteCallbackList.finishBroadcast()
        }

        val spendTime = System.currentTimeMillis() - start
        Log.d("ChangeSkin[service]", "process skin end, took ${spendTime}ms")
    }

}


